package com.wj.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.github.pagehelper.page.PageMethod;
import com.wj.domain.dto.AddShelfDTO;
import com.wj.domain.entity.BookEntity;
import com.wj.domain.entity.BookShelfEntity;
import com.wj.domain.entity.ChapterContentEntity;
import com.wj.domain.entity.ChapterEntity;
import com.wj.domain.param.BookParam;
import com.wj.domain.vo.*;
import com.wj.infrastructure.mapper.BookMapper;
import com.wj.infrastructure.mapper.BookShelfMapper;
import com.wj.infrastructure.mapper.BookTypeMapper;
import com.wj.infrastructure.mapper.NetworkConfigMapper;
import com.wj.infrastructure.repository.BookRepository;
import com.wj.infrastructure.repository.BookShelfRepository;
import com.wj.infrastructure.repository.ChapterContentRepository;
import com.wj.infrastructure.repository.ChapterRepository;
import com.wj.service.BookService;
import com.wj.service.ChapterService;
import com.wj.tool.common.utils.BookUtils;
import com.wj.tool.common.utils.CollectionUtils;
import com.wj.tool.common.utils.UuidUtils;
import com.wj.tool.common.utils.paging.Paging;
import com.wj.tool.common.utils.paging.QueryParameters;
import com.wj.tool.common.utils.paging.QueryResults;
import com.wj.tool.utils.JsoupUtil;
import com.wj.tool.utils.TimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.servlet.http.HttpServletRequest;
import javax.validation.constraints.NotNull;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

@Service
@Slf4j
public class BookServiceImpl implements BookService {

    @Resource
    private BookMapper bookMapper;

    @Resource
    private BookRepository bookRepository;

    @Resource
    private BookShelfRepository bookShelfRepository;

    @Resource
    private ChapterService chapterService;

    @Resource
    private ChapterRepository chapterRepository;

    @Resource
    private ChapterContentRepository chapterContentRepository;

    @Resource
    private BookTypeMapper bookTypeMapper;

    private Long thisUserId = 1l;

    @Resource
    private BookShelfMapper bookShelfMapper;

    @Resource
    private NetworkConfigMapper networkConfigMapper;

    @Resource
    private JdbcTemplate jdbcTemplate;

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public QueryResults<BookVO> getBookPage(QueryParameters<BookParam> parameters) {
        BookParam bookParam = parameters.getParameters();
        Paging paging = parameters.getPaging();
        PageHelper.startPage(paging.getPageNumber(), paging.getPageSize());
        List<BookVO> list = bookMapper.getList(bookParam);
        QueryResults<BookVO> queryResults = new QueryResults();
        PageInfo<BookVO> pageInfo = new PageInfo(list);
        paging.setTotalNumber((int) pageInfo.getTotal());
        paging.setTotalPages(pageInfo.getPages());
        queryResults.setPaging(paging);
        if (CollectionUtils.isNotEmpty(list)){
            for (BookVO bookVO:list){
                int type = bookVO.getType();
                String typeName = BookUtils.getTypeNameByCode(type);
                bookVO.setTypeName(typeName);
            }
        }
        queryResults.setResults(list);
        return queryResults;
    }

    @Override
    public BookVO getBookById(Long bookId) {
        BookVO bookVO = bookMapper.getById(bookId);
        if (bookVO != null){
            int type = bookVO.getType();
            String typeName = BookUtils.getTypeNameByCode(type);
            bookVO.setTypeName(typeName);

            int isInShelf = 0;
            Optional<BookShelfEntity> optional = bookShelfRepository.findByUserIdAndBookId(thisUserId, bookId);
            if (optional.isPresent()){
                BookShelfEntity bookShelfEntity = optional.get();
                isInShelf = 1;
                bookVO.setLastSort(bookShelfEntity.getSort());
            }
            bookVO.setIsInShelf(isInShelf);
        }
        return bookVO;
    }

    /**
     * 添加点击量
     * @param id
     */
    @Override
    public void addView(Long id) {
        Optional<BookEntity> optional = bookRepository.findById(id);
        if (optional.isPresent()){
            BookEntity entity = optional.get();
            entity.setViews(entity.getViews() + 1);
            bookRepository.save(entity);
        }
    }

    /**
     * 判断是否在我的书架
     * @param request
     * @param bookId
     * @return
     */
    @Override
    public int isShelf(HttpServletRequest request, Long bookId) {
        Object idObj = request.getSession().getAttribute("id");
        if (idObj != null){
            Long id = Long.valueOf(idObj.toString());
            Optional<BookShelfEntity> optional = bookShelfRepository.findByUserIdAndBookId(id, bookId);
            if (optional.isPresent()){
                return 1;
            }
        }
        return 0;
    }

    @Override
    public List<BookVO> getBookList() {
        BookParam bookParam = new BookParam();
        List<BookVO> list = bookMapper.getList(bookParam);
        List<BookVO> newList = new ArrayList<>();
        if (CollectionUtils.isNotEmpty(list)){
            for (BookVO bookVO:list){
                int type = bookVO.getType();
                String typeName = BookUtils.getTypeNameByCode(type);
                bookVO.setTypeName(typeName);
                newList.add(bookVO);
            }
        }
        return newList;
    }

    public void saveChapterBatch(List<ChapterEntity> list) {
        StringBuilder sb = intoChapter();
        Date now = new Date();
        String nowStr = DateUtil.format(now, "yyyy-MM-dd HH:mm:ss");
        int i=0;
        for (ChapterEntity entity : list) {
            i++;
            if(i>1){
                sb.append(",");
            }
            sb.append(String.format(" ('%s','%s','%s','%s','%s','%s','%s')",
                    entity.getId(),
                    entity.getBookId(),
                    entity.getChapterTitle(),
                    entity.getContentId(),
                    entity.getSort(),
                    entity.getChapterUrl(),
                    nowStr));
            //一千条执行一次
            if(i >= 1000){
//                log.info(sb.toString());
//                entityManager.createNativeQuery(sb.toString()+";").executeUpdate();
                jdbcTemplate.execute(sb.toString());
                i = 0;
                sb = intoChapter();
            }
        }
        if(i > 0){
//            entityManager.createNativeQuery(sb.toString()+";").executeUpdate();
            jdbcTemplate.execute(sb.toString());
        }

    }

    public StringBuilder intoChapter(){
        StringBuilder insert = new StringBuilder("INSERT INTO `chapter` (`id`, `book_id`, " +
                " `chapter_title`, `content_id`,`sort`,`chapter_url`,`create_time`)" +
                " VALUES ");
        return insert;
    }

    public void saveChapterContentBatch(List<ChapterContentEntity> list) {
        StringBuilder sb = intoChapterContent();
        int i=0;
        for (ChapterContentEntity entity : list) {
            i++;
            if(i>1){
                sb.append(",");
            }
            sb.append(String.format(" ('%s','%s','%s')",
                    entity.getId(),
                    entity.getBookId(),
                    entity.getContent()));
            //一千条执行一次
            if(i >= 1000){
//                log.info(sb.toString());
//                entityManager.createNativeQuery(sb.toString()+";").executeUpdate();
                jdbcTemplate.execute(sb.toString());
                i = 0;
                sb = intoChapterContent();
            }
        }
        if(i > 0){
//            entityManager.createNativeQuery(sb.toString()+";").executeUpdate();
            jdbcTemplate.execute(sb.toString());
        }

    }

    public StringBuilder intoChapterContent(){
        StringBuilder insert = new StringBuilder("INSERT INTO `chapter_content` (`id`, `book_id`, `content`)" +
                " VALUES ");
        return insert;
    }

    @Override
    public void updateBook(Long bookId, String bookUrl) {
        List<ChapterVO> list=chapterService.queryListByBookId(bookId);
        Optional<BookEntity> bookEntityOptional = bookRepository.findById(bookId);
        if (!bookEntityOptional.isPresent()){
            log.error("该小说bookId:"+bookId+"---不存在");
            return;
        }
        BookEntity bookEntity=  bookRepository.findById(bookId).get();
        log.info("正在更新："+bookEntity.getBookName());
        int dataLength=list.size();
        Document doc = JsoupUtil.getDoc(bookUrl);
        NetworkConfigVO config = networkConfigMapper.getConfig(bookUrl);
        Elements elements = doc.select("dd>a");
        int k = 12;
        if (config != null){
            k = config.getNewNum();
        }
        int elnLength=elements.size() - k;

        if (dataLength!=elnLength){
            if (dataLength==0){
                int sort = 1;
                int cot = 0;
                List<ChapterContentEntity> chapterContentEntityList = new ArrayList<>();
                List<ChapterEntity> chapterEntityList = new ArrayList<>();

                for (Element element : elements) {
                    if (cot<k){
                        cot++;
                        continue;
                    }
                    ChapterContentEntity chapterContentEntity=new ChapterContentEntity();
                    String url = element.attr("abs:href");
                    Document document = JsoupUtil.getDoc(url);
                    //章节标题
                    String title = document.select("h1").text();
                    //章节内容
                    String text = JsoupUtil.subContent(document.getElementById("content").html());
                    //保存小说内容
                    Long chapterContentId = UuidUtils.createId();
                    chapterContentEntity.setId(chapterContentId);
                    chapterContentEntity.setBookId(bookId);
                    chapterContentEntity.setContent(text);
                    chapterContentEntityList.add(chapterContentEntity);
                    //chapterContentRepository.save(chapterContent);
                    ChapterEntity chapterEntity = new ChapterEntity();
                    chapterEntity.setId(UuidUtils.createId());
                    chapterEntity.setChapterUrl(url);
                    chapterEntity.setBookId(bookId);
                    chapterEntity.setChapterTitle(title);
                    chapterEntity.setContentId(chapterContentId);
                    chapterEntity.setSort(sort);
                    chapterEntity.setCreateTime(new Date());
                    chapterEntityList.add(chapterEntity);
                    //chapterRepository.save(chapterEntity);
                    System.out.println("重新抓取小说：" + bookEntity.getBookName() + "" + title);
                    sort++;
                }
                if (CollectionUtils.isNotEmpty(chapterContentEntityList)){
                    saveChapterContentBatch(chapterContentEntityList);
                }
                if (CollectionUtils.isNotEmpty(chapterEntityList)){
                    saveChapterBatch(chapterEntityList);
                }
            }else {
                //有更新
                int i=elements.size()-dataLength;
                //最新章节下标
                int n=dataLength;
                if (bookUrl.contains("shuquge") || bookUrl.contains("biqugeg.cc")){
                    i=elements.size()-dataLength-k;
                    n=dataLength+k;
                }
                if (bookUrl.contains("xibiquge.com")){
                    i=elements.size()-dataLength-k;
                    n=dataLength+k;
                }
                System.out.println(bookEntity.getBookName()+"最新章节有："+i+"章");
                int sort=dataLength+1;

                List<ChapterContentEntity> chapterContentEntityList = new ArrayList<>();
                List<ChapterEntity> chapterEntityList = new ArrayList<>();

                for (int j=0;j<i;j++){
                    String url=elements.get(n).attr("abs:href");
                    Document document = JsoupUtil.getDoc(url);
                    //章节标题
                    String title = document.select("h1").text();
                    //章节内容
                    String text = JsoupUtil.subContent(document.getElementById("content").html());
                    //保存小说内容
                    ChapterContentEntity chapterContentEntity=new ChapterContentEntity();
                    Long chapterContentId = UuidUtils.createId();
                    chapterContentEntity.setId(chapterContentId);
                    chapterContentEntity.setBookId(bookId);
                    chapterContentEntity.setContent(text);
                    chapterContentEntityList.add(chapterContentEntity);
                    //chapterContentRepository.save(chapterContent);
                    ChapterEntity chapterEntity = new ChapterEntity();
                    chapterEntity.setId(UuidUtils.createId());
                    chapterEntity.setChapterUrl(url);
                    chapterEntity.setBookId(bookId);
                    chapterEntity.setChapterTitle(title);
                    chapterEntity.setContentId(chapterContentId);
                    chapterEntity.setSort(sort);
                    chapterEntity.setCreateTime(new Date());
                    chapterEntityList.add(chapterEntity);
                    n++;
                    sort++;//排序
                    // 设置最新章节
                    bookEntity.setNewest(title);
                }

                if (CollectionUtils.isNotEmpty(chapterContentEntityList)){
                    saveChapterContentBatch(chapterContentEntityList);
                }
                if (CollectionUtils.isNotEmpty(chapterEntityList)){
                    saveChapterBatch(chapterEntityList);
                }
                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                log.info(bookEntity.getBookName()+"今日"+simpleDateFormat.format(new Date())+"已有"+i+"章更新完成");
            }
            //更新时间
            bookEntity.setUpdateTime(TimeUtil.getTimestamp());
            //更新最新章节
            bookRepository.save(bookEntity);
        }else {
            log.info(bookEntity.getBookName()+"小说已经是最新");
        }
    }

    @Override
    public List<BookTypeVO> getTypeList() {
        List<BookTypeVO> typeList = bookTypeMapper.getTypeList();
        return typeList;
    }

    @Override
    public List<BookShelfVO> getMyBookShelfList() {
        List<BookShelfVO> list = bookShelfMapper.queryListByUserId(thisUserId);
        return list;
    }

    @Override
    public boolean removeBookShelf(Long bookId) {
        bookShelfRepository.deleteByBookIdAndUserId(bookId, thisUserId);
        return true;
    }

    @Override
    public boolean addBookShelf(AddShelfDTO shelfDTO) {
        Long bookId = shelfDTO.getBookId();
        BookShelfEntity bookShelfEntity = new BookShelfEntity();
        Optional<BookShelfEntity> optional = bookShelfRepository.findByUserIdAndBookId(thisUserId, bookId);
        if (optional.isPresent()){
            bookShelfEntity = optional.get();
        } else {
            bookShelfEntity.setId(UuidUtils.createId());
            bookShelfEntity.setBookId(bookId);
            bookShelfEntity.setUserId(thisUserId);
        }
        if (shelfDTO.getSort() == null){
            bookShelfEntity.setSort(1);
        } else {
            bookShelfEntity.setSort(shelfDTO.getSort());
        }
        bookShelfRepository.save(bookShelfEntity);
        return true;
    }
}